/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package pl.drypisy;

import java.awt.Point;
import java.awt.image.BufferedImage;

/**
 *
 * @author Marcin Piłat
 */
public class WarpProcess extends ImageProcess{
    
    double xstart;
    double ystart;
    double xend;
    double yend;
    double transx = 0;
    double transy = 0;
    double r = 50;
    public WarpMemento mem = new WarpMemento();
    
    public void countProp(double p){
        mem.countProp(p);
    }
    
    public void setCoords(int xs, int ys, int xe, int ye){
        xstart = xs;
        ystart = ys;
        xend = xe;
        yend = ye;
    }
    
    public void setR(double _r){
        r = _r;
    }
    
    public void addMemento(int x1, int y1, int x2, int y2, int r){
        mem.addPoints(x1, y1, x2, y2, r);
    }
    
    public void backMemento(){
        mem.removeLast();
    }
    
    public BufferedImage oneProcess(BufferedImage img) {
       
        srcWidth = img.getWidth();
        srcHeight = img.getHeight();
        int width = srcWidth;
        int height = srcHeight;
        BufferedImage dest = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        int[] outPixels = new int[width] ;
        int[] inPixels = img.getRGB(0, 0, srcWidth, srcHeight, null, 0, srcWidth);
        double out[] = new double[2];
        int nw, ne, sw, se;

        for (int y=0;y<height;y++) {
            for (int x=0;x<width;x++) {
                getOriginalCoordinates(x, y,out);
                int srcX = (int)Math.floor( out[0] );
                int srcY = (int)Math.floor( out[1] );
                int pix;
                if(doInterpolation) {
                    double xWeight = out[0]-srcX;
                    double yWeight = out[1]-srcY;
                    nw = getPixel( inPixels, srcX, srcY, srcWidth, srcHeight);
                    ne = getPixel( inPixels, srcX+1, srcY, srcWidth, srcHeight );
                    sw = getPixel( inPixels, srcX, srcY+1, srcWidth, srcHeight );
                    se = getPixel( inPixels, srcX+1, srcY+1, srcWidth, srcHeight );
                    pix = bilinearInterpolation(xWeight, yWeight,  nw, ne, sw, se);
                }
                else pix = getPixel(inPixels,srcX,srcY,srcWidth,srcHeight);
                outPixels[x] = pix;
            }
            dest.setRGB(0, y, width, 1, outPixels, 0, height);
        }
        return dest;
    }

    @Override
    protected void getOriginalCoordinates(int x, int y, double[] out) {
        double rmax2 = Math.pow(r,2);
        double xc = Math.pow(x-xstart,2) + Math.pow(y-ystart,2);
        if(xc <= rmax2){
            double mc = Math.pow(xend-xstart,2) + Math.pow(yend-ystart,2);
            double wsp = Math.abs((rmax2 - xc)/(rmax2+xc + mc));
            out[0] = x - wsp*(xend-xstart);
            out[1] = y - wsp*(yend-ystart);
        }else{
            out[0] = x;
            out[1] = y;
        }
    }

    @Override
    public BufferedImage process(BufferedImage img) {
        srcWidth = img.getWidth();
        srcHeight = img.getHeight();
        int width = srcWidth;
        int height = srcHeight;
        BufferedImage dest = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        int[] outPixels = new int[width] ;
        int[] inPixels = img.getRGB(0, 0, srcWidth, srcHeight, null, 0, srcWidth);
        dest.setRGB(0, 0, width, height, inPixels, 0, width);
        
        double out[] = new double[2];
        int nw, ne, sw, se;

        for(int i = 0 ; i < mem.getSize(); ++i){
            Point start = mem.getSPoint(i);
            xstart = start.x;
            ystart = start.y;
            Point end = mem.getEPoint(i);
            xend = end.x;
            yend = end.y;
            r=mem.getRad(i);
            inPixels = dest.getRGB(0, 0, width, height, null, 0, width);
            for (int y=0;y<height;y++) {
                for (int x=0;x<width;x++) {
                    getOriginalCoordinates(x, y,out);
                    int srcX = (int)Math.floor( out[0] );
                    int srcY = (int)Math.floor( out[1] );
                    int pix;
                    if(doInterpolation) {
                        double xWeight = out[0]-srcX;
                        double yWeight = out[1]-srcY;
                        nw = getPixel( inPixels, srcX, srcY, srcWidth, srcHeight);
                        ne = getPixel( inPixels, srcX+1, srcY, srcWidth, srcHeight );
                        sw = getPixel( inPixels, srcX, srcY+1, srcWidth, srcHeight );
                        se = getPixel( inPixels, srcX+1, srcY+1, srcWidth, srcHeight );
                        pix = bilinearInterpolation(xWeight, yWeight,  nw, ne, sw, se);
                    }
                    else pix = getPixel(inPixels,srcX,srcY,srcWidth,srcHeight);
                    outPixels[x] = pix;
                }
                dest.setRGB(0, y, width, 1, outPixels, 0, height);
            }
        }
        System.out.println();
        return dest;
    }
    
}
